import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { By } from '@angular/platform-browser';
import { PaginatorModule } from './paginator.module';

@Component({
  template: `
    <lv-paginator
      [lvTotal]="lvTotal"
      [lvMode]="lvMode"
      [lvShowTotal]="lvShowTotal"
      [lvPageIndex]="lvPageIndex"
      [lvPageSize]="lvPageSize"
      [lvShowQuickjump]="lvShowQuickjump"
      [lvDisabled]="lvDisabled"
    ></lv-paginator>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestPaginatorComponent {
  @Input() lvTotal: number = 0;
  @Input() lvShowTotal: boolean = true;
  @Input() lvPageIndex: number = 0;
  @Input() lvShowQuickjump: boolean = true;
  @Input() lvMode: string = 'default';
  @Input() lvDisabled: boolean;
  @Input() lvPageSize: number = 25;
}

describe('PaginatorComponent', () => {
  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [TestPaginatorComponent],
      imports: [PaginatorModule],
      teardown: { destroyAfterEach: true },
    }).compileComponents();
  }));

  describe('render', () => {
    let component: TestPaginatorComponent;
    let fixture: ComponentFixture<TestPaginatorComponent>;
    let cdr: ChangeDetectorRef;

    const renderComponent = fakeAsync(param => {
      for (const [key, value] of Object.entries(param)) {
        component[key] = value;
      }
      cdr.detectChanges();
      tick(500);
      expect(fixture).toMatchSnapshot();
    });

    beforeEach(() => {
      fixture = TestBed.createComponent(TestPaginatorComponent);
      component = fixture.componentInstance;
      cdr = fixture.debugElement.injector.get(ChangeDetectorRef);
    });

    // 配置数据总数 total(0)，传入lvShowTotal为true和false渲染
    it('with lvTotal', () => {
      renderComponent({ lvTotal: 0, lvShowTotal: true });
      renderComponent({ lvShowTotal: false });
    });

    // 页码小于等于7渲染（不显示省略号）
    it('when page less than 7', () => {
      renderComponent({ lvTotal: 100 });
    });

    // 页码大于7渲染（显示省略号）（配置lvPageIndex处于不同位置）
    it('when page greater than 7', () => {
      renderComponent({ lvTotal: 225, lvPageIndex: 1 });
      renderComponent({ lvTotal: 225, lvPageIndex: 5 });
    });

    // 精简模式渲染
    it('when lvMode pass simple', () => {
      renderComponent({ lvTotal: 225, lvMode: 'simple' });
    });

    // lvShowQuickJump传入false渲染
    it('when lvShowQuickJump pass false', () => {
      renderComponent({ lvTotal: 225, lvShowQuickjump: false });
    });
  });

  describe('work', () => {
    let component: TestPaginatorComponent;
    let fixture: ComponentFixture<TestPaginatorComponent>;

    const selectedClass = '.selected';
    const ellipsisClass = '.lv-paginator-ellipsis-button';
    const numClass = '.lv-paginator-number-button';
    const prevClass = '.lv-paginator-previous';
    const nextClass = '.lv-paginator-next';

    const detectChanges = () => {
      tick(500);
      fixture.detectChanges();
    };

    beforeEach(() => {
      fixture = TestBed.createComponent(TestPaginatorComponent);
      component = fixture.componentInstance;
    });
    // 点击上一页，下一页，能正常切换当前页码
    it('when click prev and next', fakeAsync(() => {
      component.lvTotal = 225;
      fixture.detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');

      const next = fixture.nativeElement.querySelector(nextClass);
      next.dispatchEvent(new Event('click'));
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('2');

      const prev = fixture.nativeElement.querySelector(prevClass);
      prev.dispatchEvent(new Event('click'));
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');
    }));

    // disabled状态下分页器无法使用
    it('should not work when disabled', fakeAsync(() => {
      component.lvTotal = 225;
      component.lvDisabled = true;
      fixture.detectChanges();

      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');
      const num5 = fixture.nativeElement.querySelectorAll(numClass)[4];
      num5.dispatchEvent(new Event('click'));
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');
    }));

    // 点击省略号能快速跳转
    it('when click the ellipsis', fakeAsync(() => {
      component.lvTotal = 225;
      fixture.detectChanges();

      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');
      const ellipsis = fixture.nativeElement.querySelector(ellipsisClass);
      ellipsis.dispatchEvent(new Event('click'));
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('6');
    }));

    // 输入具体页码跳转（能自动校正，小于最小页变更为最小页，大于最大页变更为最大页）
    it('when input the pageNum', fakeAsync(() => {
      component.lvTotal = 225;
      fixture.detectChanges();

      const debugInput = fixture.debugElement.query(By.css('.lv-input'));
      const input = fixture.nativeElement.querySelector('.lv-input');
      input.value = '3';
      debugInput.triggerEventHandler('input', { data: '3' });
      detectChanges();

      const e = new KeyboardEvent('keydown', {
        code: 'Enter',
        key: 'Enter',
        view: window,
        bubbles: true,
      });
      input.dispatchEvent(e);
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('3');

      input.value = '0';
      debugInput.triggerEventHandler('input', { data: '0' });
      detectChanges();
      input.dispatchEvent(e);
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('1');

      input.value = '11';
      debugInput.triggerEventHandler('input', { data: '11' });
      detectChanges();
      input.dispatchEvent(e);
      detectChanges();
      expect(fixture.nativeElement.querySelector(selectedClass).textContent).toContain('9');
    }));
  });
});
